from django.shortcuts import render
from django.views import View
from django.http import JsonResponse

import json
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utils.cookiesecret import CookieSecret
# Create your views here.



class CartsView(View):

    # 新建购物车
    def post(self, request):
        # 1、提取参数
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)

        # 2、校验参数
        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'})

        try:
            sku = SKU.objects.get(pk=sku_id, is_launched=True)
        except SKU.DoesNotExist as e:
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})


        # 3、业务数据处理
        user = request.user
        if user.is_authenticated:
            # 3.1、登陆，存redis
            conn = get_redis_connection('carts') # 5号库
            # (1)、存哈希键值对
            # hset函数给redis哈希对象新建键值对是"覆盖"操作
            # conn.hset('carts_%s'%user.id, sku_id, count)
            # hincrby函数给redis哈希对象的键的值进行"累加"操作
            conn.hincrby('carts_%s'%user.id, sku_id, count)
            # (2)、判断是否选择，选中则加入集合，未选中则集合中剔除
            if selected:
                conn.sadd('selected_%s'%user.id, sku_id)
            else:
                conn.srem('selected_%s'%user.id, sku_id)

            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 3.2、未登陆，存cookie
            # (1)、从cookie中提取购物车字典数据(使用pickle和base64解码)
            # carts : "bhgubrghtl5b4jgljr43;krm5'4kty6op5;y"
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # cookie中有购物车加密的字符串数据，此处需要解密出原来的购物车字典
                cart_dict = CookieSecret.loads(cart_str)
            else:
                cart_dict = {}

            # (2)、往购物车字典中新增当前新加入的购物车数据
            if sku_id in cart_dict:
                # sku_id存在，则累加count
                cart_dict[sku_id]['count'] += count
                cart_dict[sku_id]['selected'] = selected
            else:
                # sku_id不存在，则新建键值对
                cart_dict[sku_id] = {
                    'count': count,
                    'selected': selected
                }

            # (3)、把新的购物车字典数据编码加密成字符串写入cookie
            new_cart_str = CookieSecret.dumps(cart_dict)
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', new_cart_str)
            return response

    # 展示购物车
    def get(self, request):
        user = request.user

        # 编码习惯：通常定义一个变量来记录后续在不同
        # 逻辑分之中读取的数据，便于后续统一处理
        # TODO: 约定一个变量，其值的格式是"购物车字典结构的数据"
        cart_dict = {}

        if user.is_authenticated:
            # 登陆，从redis中读取购物车数据
            conn = get_redis_connection('carts')
            # {b'11': b'3', b'5': b'6'} --> 11号商品买了3个....
            redis_carts = conn.hgetall('carts_%s'%user.id)
            # [b'11', b'5'] --> 11号商品和5号商品被选中
            redis_selected = conn.smembers('selected_%s'%user.id)
            for k,v in redis_carts.items():
                # k=b'11'; v=b'3'
                sku_id = int(k)
                count = int(v)
                cart_dict[sku_id] = {
                    'count': count,
                    'selected': k in redis_selected # b'11' in [b'11', b'5']
                }
        else:
            # 未登陆，从cookie中读取购物车数据
            cart_str = request.COOKIES.get('carts') # 读取加密的字符串数据
            if cart_str:
                # 解密成购物车字典
                cart_dict = CookieSecret.loads(cart_str)

        # TODO: 操作上述的cart_dict进一步读取sku的详细信息
        # cart_dict = {11: {"count":3, "selected": True}, 5: {"count": 6, "selected": True}}
        cart_skus = [] # 构建响应参数
        for k,v in cart_dict.items():
            # k=11; v={"count":3, "selected": True}
            sku = SKU.objects.get(pk=k)
            cart_skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'count': v['count'],
                'selected': v['selected']
            })

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus':cart_skus})

    # 修改购物车
    def put(self, request):
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)

        if not all([sku_id, count]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必要参数'})

        try:
            sku = SKU.objects.get(pk=sku_id, is_launched=True)
        except SKU.DoesNotExist as e:
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        # TODO: 修改购物车
        user = request.user
        if user.is_authenticated:
            # 登陆修改redis购物车
            conn = get_redis_connection('carts') # 5
            # (1)、修改哈希对象(把新的sku_id和count以"覆盖"写入)
            conn.hset('carts_%s'%user.id, sku_id, count)
            # (2)、根据selected最新状态操作集合
            if selected:
                conn.sadd('selected_%s'%user.id, sku_id)
            else:
                conn.srem('selected_%s' % user.id, sku_id)
            return JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'sku_id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })
        else:
            # 未登陆修改cookie购物车
            # (1)、读取cookie中的购物车字典数据
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = CookieSecret.loads(cart_str)
            else:
                cart_dict = {}
            # (2)、基于新数据，构造新的购物车字典
            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }
            # (3)、把新字典数据加密编码写入cookie
            new_cart_str = CookieSecret.dumps(cart_dict)
            response = JsonResponse({
                'code': 0,
                'errmsg': 'ok',
                'cart_sku': {
                    'sku_id': sku_id,
                    'count': count,
                    'selected': selected
                }
            })
            response.set_cookie('carts', new_cart_str)
            return response

    # 删除购物车
    def delete(self, request):

        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')

        if not sku_id:
            return JsonResponse({'code': 400, 'errmsg': '缺少sku_id参数'})

        try:
            sku = SKU.objects.get(pk=sku_id)
        except SKU.DoesNotExist as e:
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        user = request.user
        if user.is_authenticated:
            # 登陆，删除redis购物车
            conn = get_redis_connection('carts')
            # (1)、删除redis哈希对象中的键sku_id
            conn.hdel('carts_%s'%user.id, sku_id)
            # (2)、删除sku_id的勾选状态
            conn.srem('selected_%s'%user.id, sku_id)
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 未登陆，删除cookie购物车
            # (1)、读取cookie购物车字典数据
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = CookieSecret.loads(cart_str)
            else:
                cart_dict = {}
            # (2)、根据sku_id删除字典中的键值对
            if sku_id in cart_dict:
                del cart_dict[sku_id]
            # (3)、把新的字典加密编码成字符串写入cookie
            new_cart_str = CookieSecret.dumps(cart_dict)
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', new_cart_str)
            return response



class CartsSelectAllView(View):

    # 购物车全选
    def put(self, request):
        data = json.loads(request.body.decode())
        selected = data.get('selected', True)

        user = request.user
        if user.is_authenticated:
            # 登陆，把redis购物车所有商品的id，添加到集合中表示选中
            conn = get_redis_connection('carts')
            # redis_carts = {b'11': b'5', b'6': 3}
            redis_carts = conn.hgetall('carts_%s'%user.id)
            # sku_ids = [b'11', b'6']
            sku_ids = redis_carts.keys()
            if selected:
                # 把购物车所有商品id加入集合
                conn.sadd('selected_%s'%user.id, *sku_ids) # *sku_ids --列表拆包--> *[b'11', b'6'] --> b'11', b'6'
            else:
                # 把购物车所有商品id从集合中剔除
                conn.srem('selected_%s' % user.id, *sku_ids)
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:
            # 未登陆，把cookie购物车字典中所有的商品selected状态设置未True
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = CookieSecret.loads(cart_str)
            else:
                cart_dict = {}
            # cart_dict = {11: {'count':5, 'selected': False}}
            sku_ids = cart_dict.keys()
            for sku_id in sku_ids:
                cart_dict[sku_id]['selected'] = selected
            new_cart_str = CookieSecret.dumps(cart_dict)
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', new_cart_str)
            return response


# 展示简单购物车
class CartsSimpleView(View):

    def get(self, request):
        user = request.user

        # 约定一个变量，来记录从redis或从cookie中读取的购物车数据
        # 格式约定：一个购物车字典如{11:{'count':5, 'selected': True}}
        cart_dict = {}

        if user.is_authenticated:
            # 登陆，展示redis购物车
            conn = get_redis_connection('carts')
            # redis_carts = {b'11': b'5', b'6': b'3'}
            redis_carts = conn.hgetall('carts_%s'%user.id)
            # redis_selected = [b'11', b'6']
            redis_selected = conn.smembers('selected_%s'%user.id)
            for k,v in redis_carts.items():
                sku_id = int(k)
                count = int(v)
                cart_dict[sku_id] = {
                    'count': count,
                    'selected': k in redis_selected # b'11' in [b'11', b'6']
                }
        else:
            # 未登陆，展示cookie购物车
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = CookieSecret.loads(cart_str)

        # cart_dict = {11:{'count':5, 'selected': True}}
        # 从musql中进一步读取详细信息，构建响应参数返回
        cart_skus = []
        sku_ids = cart_dict.keys()
        for sku_id in sku_ids:
            if cart_dict[sku_id]['selected']: # 只显示勾选了的sku
                sku = SKU.objects.get(pk=sku_id)
                cart_skus.append({
                    'id': sku.id,
                    'name': sku.name,
                    'count': cart_dict[sku_id]['count'],
                    'default_image_url': sku.default_image.url
                })

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})




